package com.platform.data.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.platform.base.domain.CollectorInfo;
import com.platform.base.domain.UnitValveInfo;
import com.platform.base.domain.ValveInfo;
import com.platform.base.mapper.CollectorInfoMapper;
import com.platform.base.mapper.UnitValveInfoMapper;
import com.platform.base.mapper.ValveInfoMapper;
import com.platform.common.exception.BusinessException;
import com.platform.common.utils.DateUtils;
import com.platform.common.utils.netty.NettyUtil;
import com.platform.common.utils.rabbit.RabbitUtils;
import com.platform.common.utils.redis.RedisRun;
import com.platform.common.utils.redis.RedisUtil;
import com.platform.data.domain.UnitValveData;
import com.platform.data.domain.UnitValveData;
import com.platform.data.domain.ValveData;
import com.platform.data.mapper.UnitValveDataMapper;
import com.platform.data.mapper.ValveDataMapper;
import com.platform.data.service.IUnitValveDataService;
import com.platform.data.service.IValveDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 阀门采集数据Service业务层处理
 * 
 * @author wangqi
 * @date 2020-09-27
 */
@Service
public class UnitValveDataServiceImpl extends ServiceImpl<UnitValveDataMapper, UnitValveData> implements IUnitValveDataService
{
    @Autowired
    private UnitValveDataMapper unitValveDataMapper;

    @Autowired
    private UnitValveInfoMapper unitValveInfoMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RabbitUtils rabbitUtils;

    @Autowired
    private CollectorInfoMapper collectorInfoMapper;

    /**
     * 查询阀门采集数据列表
     * 
     * @param unitValveData 阀门采集数据
     * @return 阀门采集数据
     */
    @Override
    public List<UnitValveData> selectUnitValveDataList(UnitValveData unitValveData)
    {
        return unitValveDataMapper.selectUnitValveDataList(unitValveData);
    }
    /**
     * 查询阀门采集数据列表
     *
     * @param unitValveData 阀门采集数据
     * @return 阀门采集数据
     */
    @Override
    public List<UnitValveData> selectUnitValveDatarList(UnitValveData unitValveData)
    {
        return unitValveDataMapper.selectUnitValveDatarList(unitValveData);
    }

    /**
     * 新增阀门采集数据
     * 
     * @param unitValveData 阀门采集数据
     * @return 结果
     */
    @Override
    @Transactional
    public int insertUnitValveData(UnitValveData unitValveData)
    {
        unitValveData.setCreateTime(DateUtils.getNowDate());
        return unitValveDataMapper.insert(unitValveData);
    }

    /**
     * 读取阀门数据
     * @param valveId 阀门信息
     * @return
     * @throws Exception
     */
    @Override
    public String checkData(String valveId) throws InterruptedException {
        UnitValveInfo info = null;

        if(redisUtil.hHasKey("unitValve-info", valveId)){
            info = (UnitValveInfo) redisUtil.hget("unitValve-info", valveId);
        }else{
            info = unitValveInfoMapper.selectUnitValveInfoById(valveId);
        }

        if(info.getCollectorId() == null || info.getCollectorId().equals("")){
            return "阀门 " + info.getValveId() + " 未关联采集器";
        }

        //判断采集器是否在线
        boolean status = redisUtil.hHasKey("sys-netty", info.getCollectorId());
        if(!status){
            return "阀门 " + info.getValveId() + "关联的采集器" + info.getCollectorId() + " 已离线";
        }
        //获取采集器高位
        String cenhigh = info.getCollectorId().substring(0,2);
        //获取采集器低位
        String cenlow = info.getCollectorId().substring(2,4);
        //阀门
        String fmdz = NettyUtil.get16HexNum(Integer.parseInt(valveId));
        //控制码
        String cont = "14";
        //校验
        String jy = "01";
        //寄存器地址
        String jcq = "51";
        //字节数
        String zjs = "0E";
        //计算校验码
        int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(fmdz)+NettyUtil.get10HexNum(jy)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(jcq)+NettyUtil.get10HexNum(zjs);
        String check = NettyUtil.get16HexNum(ll);
        if(check.length()<2){
            check = "0" + check;
        }else{
            check = check.substring(check.length()-2);
        }
        String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " " + jy + " " + fmdz + " 00 "  + jcq + " " + "00 "  + zjs + " " + check + " FF ";
        String responseStr = response.replace(" ", "");
        rabbitUtils.writeToClient(info.getCollectorId(), responseStr, "阀门"+valveId+"数据采集");
        CountDownLatch countDownLatch = new CountDownLatch(1);
        new Thread(new RedisRun(countDownLatch, redisUtil, valveId, cont)).start();
        countDownLatch.await();
        String result = RedisRun.result;
        if(result.equals("00")){
            return "阀门 " + valveId + " 采集成功";
        }else{
            return "阀门 " + valveId + " 采集失败";
        }
    }

    /**
     * 设置阀门开度
     * @param valveId 阀门信息
     * @param hex 阀门开度值
     * @return
     * @throws Exception
     */
    @Override
    public String apertureData(String valveId,String hex) throws InterruptedException {
        int failureNum = 0;
        int successNum = 0;
        StringBuilder failureMsg = new StringBuilder();
        StringBuilder successMsg = new StringBuilder();

            UnitValveInfo info = null;

            if(redisUtil.hHasKey("unitValve-info", valveId)){
                info = (UnitValveInfo) redisUtil.hget("unitValve-info", valveId);
            }else{
                info = unitValveInfoMapper.selectUnitValveInfoById(valveId);
                redisUtil.hset("unitValve-info", valveId, info, 60000);
            }

            if(info.getCollectorId() == null || info.getCollectorId().equals("")){
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、阀门 " + info.getValveId() + " 未关联采集器");
            }

            //判断采集器是否在线
            boolean status = redisUtil.hHasKey("sys-netty", info.getCollectorId());
            if(!status){
                failureNum++;
                CollectorInfo cinfo = collectorInfoMapper.selectCollectorInfoById(info.getCollectorId());
                cinfo.setOnlineStatus(Integer.valueOf(0));
                cinfo.setCollectorId(info.getCollectorId());
                collectorInfoMapper.updateById(cinfo);
                failureMsg.append("<br/>" + failureNum + "、阀门 " + info.getValveId() + "关联的采集器" + info.getCollectorId() + " 已离线");
            }
            //获取采集器高位
            String cenhigh = info.getCollectorId().substring(0,2);
            //获取采集器低位
            String cenlow = info.getCollectorId().substring(2,4);
        //阀门
        String fmdz = NettyUtil.get16HexNum(Integer.parseInt(valveId));

        //校验
        String jy = "01";
        //寄存器地址
        String jcq = "54";

        //控制码
        String cont = "15";
        //计算校验码
        int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(fmdz)+NettyUtil.get10HexNum(jy)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(jcq)+NettyUtil.get10HexNum(hex);
        String check = NettyUtil.get16HexNum(ll);
        if(check.length()<2){
            check = "0" + check;
        }else{
            check = check.substring(check.length()-2);
        }
        String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " " + jy + " " + fmdz + " 00 "  + jcq + " " + "00 "  + hex + " " + check + " FF ";
            String responseStr = response.replace(" ", "");
            rabbitUtils.writeToClient(info.getCollectorId(), responseStr, "设置阀门开度");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch, redisUtil, valveId, cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            redisUtil.del(valveId);
            if(!result.equals("00")){
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、阀门 " + info.getValveId() + " 设置阀门开度失败");
            }else{
                successNum++;
                successMsg.append("<br/>" + successNum + "、阀门 " + info.getValveId() + " 设置阀门开度成功");
            }

        if(failureNum>0){
            failureMsg.insert(0, "很抱歉，设置阀门开度失败！共 " + failureNum + " 条设置阀门开启失败，错误如下：");
            throw new BusinessException(failureMsg.toString());
        }else{
            successMsg.insert(0, "恭喜您，阀门已全部设置阀门开度成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }


}
